package View;

import Model.MonteCarloSimulation;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

/**
 * Created by Romain DUTARTRE on 07/02/14.
 */
public class MonteCarloGUI extends JFrame implements ActionListener, ListSelectionListener {

    public JTextField getCallPutTxt() {
        return callPutTxt;
    }

    public void setCallPutTxt(JTextField callPutTxt) {
        this.callPutTxt = callPutTxt;
    }

    public JTextField getActualPriceTxt() {
        return stockPriceTxt;
    }

    public void setActualPriceTxt(JTextField actualPriceTxt) {
        this.stockPriceTxt = actualPriceTxt;
    }

    public JTextField getStrikePriceTxt() {
        return strikePriceTxt;
    }

    public void setStrikePriceTxt(JTextField strikePriceTxt) {
        this.strikePriceTxt = strikePriceTxt;
    }

    public JTextField getMaturityTxt() {
        return maturityTxt;
    }

    public void setMaturityTxt(JTextField maturityTxt) {
        this.maturityTxt = maturityTxt;
    }

    public JTextField getInterestTxt() {
        return interestTxt;
    }

    public void setInterestTxt(JTextField interestTxt) {
        this.interestTxt = interestTxt;
    }

    public JTextField getRateTxt() {
        return rateTxt;
    }

    public void setRateTxt(JTextField rateTxt) {
        this.rateTxt = rateTxt;
    }

    public JTextField getVolatilityTxt() {
        return volatilityTxt;
    }

    public void setVolatilityTxt(JTextField volatilityTxt) {
        this.volatilityTxt = volatilityTxt;
    }

    public JTextField getStepsTxt() {
        return stepsTxt;
    }

    public void setStepsTxt(JTextField stepsTxt) {
        this.stepsTxt = stepsTxt;
    }

    public JTextField getSimuTxt() {
        return simuTxt;
    }

    public void setSimuTxt(JTextField simuTxt) {
        this.simuTxt = simuTxt;
    }

    private String [] columns = { "call/put","s","x","t","r","b","v","nSteps","nSimulation",};

    private Object [][] data = {} ;

    private JPanel container, topPanel, bottomPanel, buttonPanel;
    private JButton singleThread, multiThread;
    private JTable simulationList;
    private DefaultTableModel defaultTableModel;
    private JScrollPane simulationPane;
    private JLabel simuTimeLbl, resultLbl;

    private JTextField callPutTxt, stockPriceTxt, strikePriceTxt, maturityTxt, interestTxt, rateTxt, volatilityTxt, stepsTxt, simuTxt;

    public MonteCarloGUI() {

        container = new JPanel(new GridLayout(3,1));
        topPanel = new JPanel(new GridLayout());
        bottomPanel = new JPanel(new GridLayout(5,4));
        buttonPanel = new JPanel(new GridLayout(2,2));

        defaultTableModel = new DefaultTableModel( data, columns );
        loadFromCSV();

        simulationList = new JTable( defaultTableModel );
        simulationPane = new JScrollPane(simulationList);

        simuTimeLbl = new JLabel("Simulation time: ");
        resultLbl = new JLabel("Result: ");

        callPutTxt = new JTextField();
        stockPriceTxt = new JTextField();
        strikePriceTxt = new JTextField();
        maturityTxt = new JTextField();
        interestTxt = new JTextField();
        rateTxt = new JTextField();
        volatilityTxt = new JTextField();
        stepsTxt = new JTextField();
        simuTxt = new JTextField();

        callPutTxt.setHorizontalAlignment(JLabel.CENTER);
        stockPriceTxt.setHorizontalAlignment(JLabel.CENTER);
        strikePriceTxt.setHorizontalAlignment(JLabel.CENTER);
        maturityTxt.setHorizontalAlignment(JLabel.CENTER);
        interestTxt.setHorizontalAlignment(JLabel.CENTER);
        rateTxt.setHorizontalAlignment(JLabel.CENTER);
        volatilityTxt.setHorizontalAlignment(JLabel.CENTER);
        stepsTxt.setHorizontalAlignment(JLabel.CENTER);
        simuTxt.setHorizontalAlignment(JLabel.CENTER);

        singleThread = new JButton("SINGLETHREAD MODE");
        multiThread = new JButton("MULTITHREAD MODE");

        singleThread.addActionListener(this);
        multiThread.addActionListener(this);

        topPanel.add(simulationPane);

        bottomPanel.add(new JLabel("Call or Put (call or put)"));
        bottomPanel.add(callPutTxt);
        bottomPanel.add(new JLabel("Stock Price (s)"));
        bottomPanel.add(stockPriceTxt);
        bottomPanel.add(new JLabel("Strike Price (x)"));
        bottomPanel.add(strikePriceTxt);
        bottomPanel.add(new JLabel("Maturity (t)"));
        bottomPanel.add(maturityTxt);
        bottomPanel.add(new JLabel("''No risk'' interest rate (r)"));
        bottomPanel.add(interestTxt);
        bottomPanel.add(new JLabel("Carry rate cost (r)"));
        bottomPanel.add(rateTxt);
        bottomPanel.add(new JLabel("Volatility (v)"));
        bottomPanel.add(volatilityTxt);
        bottomPanel.add(new JLabel("Step number (nSteps)"));
        bottomPanel.add(stepsTxt);
        bottomPanel.add(new JLabel("Simulation number (nSimulation)"));
        bottomPanel.add(simuTxt);

        callPutTxt.setText(simulationList.getValueAt(0, 0).toString());
        stockPriceTxt.setText(simulationList.getValueAt(0, 1).toString());
        strikePriceTxt.setText(simulationList.getValueAt(0, 2).toString());
        maturityTxt.setText(simulationList.getValueAt(0, 3).toString());
        interestTxt.setText(simulationList.getValueAt(0, 4).toString());
        rateTxt.setText(simulationList.getValueAt(0, 5).toString());
        volatilityTxt.setText(simulationList.getValueAt(0, 6).toString());
        stepsTxt.setText(simulationList.getValueAt(0, 7).toString());
        simuTxt.setText(simulationList.getValueAt(0, 8).toString());

        simulationList.getSelectionModel().addListSelectionListener(this);

        simuTimeLbl.setHorizontalAlignment(JLabel.CENTER);
        resultLbl.setHorizontalAlignment(JLabel.CENTER);

        buttonPanel.add(simuTimeLbl);
        buttonPanel.add(resultLbl);
        buttonPanel.add(singleThread);
        buttonPanel.add(multiThread);

        container.add(topPanel);
        container.add(bottomPanel);
        container.add(buttonPanel);

        this.add(container);

        setResizable(false);
        setTitle("Monte Carlo App");
        setSize(800, 600);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }


    private void loadFromCSV()
    {
        Scanner inputStream;
        File fichier = new File("src/montecarlo.csv");
        defaultTableModel.setRowCount(0);

        try {
            inputStream = new Scanner(fichier);
            while (inputStream.hasNext()) {
                String data = inputStream.nextLine();
                String dataTab[] = data.split(";");
                defaultTableModel.addRow(dataTab);
            }
            inputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void actionPerformed(ActionEvent e) {

        if(e.getSource()== singleThread) {
                singleThreadMode();
        }
        if(e.getSource() == multiThread) {

                multiThreadMode();
        }
    }

    @Override
    public void valueChanged(ListSelectionEvent e) {

        ListSelectionModel lsm = (ListSelectionModel)e.getSource();

        callPutTxt.setText(simulationList.getValueAt(lsm.getMinSelectionIndex(), 0).toString());
        stockPriceTxt.setText(simulationList.getValueAt(lsm.getMinSelectionIndex(), 1).toString());
        strikePriceTxt.setText(simulationList.getValueAt(lsm.getMinSelectionIndex(), 2).toString());
        maturityTxt.setText(simulationList.getValueAt(lsm.getMinSelectionIndex(), 3).toString());
        interestTxt.setText(simulationList.getValueAt(lsm.getMinSelectionIndex(), 4).toString());
        rateTxt.setText(simulationList.getValueAt(lsm.getMinSelectionIndex(), 5).toString());
        volatilityTxt.setText(simulationList.getValueAt(lsm.getMinSelectionIndex(), 6).toString());
        stepsTxt.setText(simulationList.getValueAt(lsm.getMinSelectionIndex(), 7).toString());
        simuTxt.setText(simulationList.getValueAt(lsm.getMinSelectionIndex(), 8).toString());


    }

    public void singleThreadMode() {

        double result = 0;

        long startTime = System.currentTimeMillis();

        MonteCarloSimulation mcs = new MonteCarloSimulation(
                callPutTxt.getText(),
                Double.parseDouble(stockPriceTxt.getText()),
                Double.parseDouble(strikePriceTxt.getText()),
                Double.parseDouble(maturityTxt.getText()),
                Double.parseDouble(interestTxt.getText()),
                Double.parseDouble(rateTxt.getText()),
                Double.parseDouble(volatilityTxt.getText()),
                Integer.parseInt(stepsTxt.getText()),
                Integer.parseInt(simuTxt.getText())
        );

        result = mcs.MonteCarloStandardOption();

        long endTime = System.currentTimeMillis();

        simuTimeLbl.setText("Simulation time: " + (endTime-startTime));
        resultLbl.setText("Resut: " + result);

    }

    public void multiThreadMode() {

        double result = 0;

        long startTime = System.currentTimeMillis();

        MonteCarloSimulation mcs = new MonteCarloSimulation(
                callPutTxt.getText(),
                Double.parseDouble(stockPriceTxt.getText()),
                Double.parseDouble(strikePriceTxt.getText()),
                Double.parseDouble(maturityTxt.getText()),
                Double.parseDouble(interestTxt.getText()),
                Double.parseDouble(rateTxt.getText()),
                Double.parseDouble(volatilityTxt.getText()),
                Integer.parseInt(stepsTxt.getText()),
                Integer.parseInt(simuTxt.getText())
        );

        try {
            result = mcs.MonteCarloStandardOptionMultiThread();
        } catch (Exception e) {
            e.printStackTrace();
        }

        long endTime = System.currentTimeMillis();

        simuTimeLbl.setText("Simulation time: " + (endTime-startTime));
        resultLbl.setText("Result: " + result);

    }

}
